package MyArrayList;

import java.util.Arrays;

public class MyArrayList<T> {
    private Object[] elem;
    private int size;
    private int maxNum;
    public MyArrayList() {
        this(10);
    }
    public MyArrayList(int num) {
        this.maxNum = num;
        this.elem = new Object[maxNum];
    }
    public void grow() {
        int maxNum = Math.max(this.size/2 + this.size, this.maxNum);
        this.grow(maxNum);
    }
    public void grow(int maxNum) {
        this.elem = Arrays.copyOf(this.elem, maxNum);
        this.maxNum = maxNum;
    }
    public boolean isEmpty() {
        return this.size == 0;
    }
    public boolean isFull() {
        return this.size >= this.maxNum;
    }
    public int size() {
        return this.size;
    }
    public boolean add(T o) {
        this.add(this.size, o);
        return true;
    }
    public void add(int index, T o) {
        if(this.isFull()) {
            this.grow();
        }
        if(index > this.size || index < 0) {
            return;
        }
        for(int i = this.size; i > index; i++) {
            this.elem[i] = this.elem[i-1];
        }
        this.elem[index] = o;
        this.size++;
    }
    public T get(int index) {
        if(index >= this.size || index < 0) {
            return null;
        }
        return (T)this.elem[index];
    }
    public T set(int index, T o) {
        if(index < 0 || index >= this.size) {
            return null;
        }
        Object tmp = this.elem[index];
        this.elem[index] = o;
        return (T)tmp;
    }
    public T remove(int index) {
        if(index < 0 || index >= this.size) {
            return null;
        }
        Object tmp = this.elem[index];
        this.size--;
        for(int i = index; i < this.size; i++) {
            this.elem[i] = this.elem[i+1];
        }
        this.elem[this.size] = null;
        return (T)tmp;
    }
    public boolean remove(T key) {
        if(this.isEmpty()) {
            return false;
        }
        for(int i = 0; i < this.size; i++) {
            if(key.equals(this.elem[i])) {
                this.size--;
                for(int j = i; j < this.size; j++) {
                    this.elem[j] = this.elem[j+1];
                }
                this.elem[this.size] = null;
                return true;
            }
        }
        return false;
    }
    public int removeAll(T key) {
        if(this.isEmpty()) {
            return 0;
        }
        int num = 0;
        for(int i  = 0; i < this.size;) {
            if(key.equals(this.elem[i])) {
                this.size--;
                for(int j = i; j < this.size; j++) {
                    this.elem[j] = this.elem[j+1];
                }
                this.elem[this.size] = null;
                num++;
            }else {
                i++;
            }
        }
        return num;
    }
    public T pop(int index) {
        if(index >= this.size || index < 0) {
            return null;
        }
        this.size--;
        Object tmp = this.elem[index];
        for(int i = index; i < this.size; i++) {
            this.elem[i] = this.elem[i+1];
        }
        return (T)tmp;
    }
    public  void clear() {
        for(int i = 0; i < this.size; i++) {
            this.elem[i] = null;
        }
        this.size = 0;
    }
    public boolean addFirst(T o) {
        if(this.isFull()) {
            return false;
        }
        for(int i = this.size; i > 0; i--) {
            this.elem[i] = this.elem[i-1];
        }
        this.elem[0] = o;
        this.size++;
        return true;
    }
    public void disPlay() {
        for(int i = 0; i < this.size; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }
    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        str.append("[");
        for(int i = 0; i < this.size; i++) {
            if(i != 0) {
                str.append(", ");
            }
            str.append(this.elem[i]);
        }
        str.append("]");
        return str.toString();
    }
    public Object[] toArray() {
        return Arrays.copyOf(this.elem, this.size);
    }
}
